﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Text.RegularExpressions;
using HWorld.Networking;

namespace ROrganizer.Client
{
    public class HashGateway
    {
        private static ROrganizerProxy.rorganizerPortTypeClient CreateClient()
        {
            var binding = new BasicHttpBinding();
            var endpoint = new EndpointAddress("http://amacal.pl/rorganizer/server.php");

            return new ROrganizerProxy.rorganizerPortTypeClient(binding, endpoint);
        }

        public HashInfo Query(HashEntry entry)
        {
            var client = HashGateway.CreateClient();
            var info = new ROrganizerProxy.LookupInfo { Hash = entry.Info.Hash, Timestamp = entry.Info.LinkTimestamp ?? DateTime.Parse("2010-01-01") };
            var result = client.Lookup(info);

            if (result == null)
                return null;

            entry.IsChanged = false;

            return entry.Info = new HashInfo
            {
                Hash = entry.Info.Hash,
                Link = result.Link,
                LinkTimestamp = result.Timestamp,
            };
        }

        public bool Commit(HashCredentials credentials, HashEntry entry)
        {
            var client = HashGateway.CreateClient();
            var info = new ROrganizerProxy.CommitInfo { Hash = entry.Info.Hash, Link = entry.Info.Link };
            var result = client.Commit(credentials.Username, credentials.Password, info);

            if (result.Success)
                entry.IsChanged = false;

            return result.Success;
        }

        public bool Commit(HashCredentials credentials, string hash, string link)
        {
            var client = HashGateway.CreateClient();
            var info = new ROrganizerProxy.CommitInfo { Hash = hash, Link = link };
            var result = client.Commit(credentials.Username, credentials.Password, info);

            return result.Success;
        }

        public HashCaptcha GetCaptcha(HNetworkChannel channel = null)
        {
            var session = new HNetworkSession(channel: channel);
            var curl = @"http://www.google.com/recaptcha/api/challenge?k=6Lewm7sSAAAAAKr5IsRPVGq0nPlCyOukf8FQnGyq";
            var iurl = @"http://www.google.com/recaptcha/api/image?c={0}";

            using (var cdata = session.Get(curl))
            {
                var script = cdata.GetText();
                var challenge = Regex.Match(script, @"challenge\s*:\s*'(?<challenge>[^']+)'").Groups["challenge"].Value;

                using (var idata = session.Get(String.Format(iurl, challenge)))
                {
                    var image = idata.GetBytes();
                    var result = new HashCaptcha { Challenge = challenge, Image = image };

                    return result;
                }
            }
        }

        public bool CreateUser(HashCaptcha captcha, string username, string password, string code)
        {
            var client = HashGateway.CreateClient();
            var result = client.CreateUser(username, password, captcha.Challenge, code);

            return result;
        }

        public HashProposal[] GetProposals(HashCredentials credentials)
        {
            var client = HashGateway.CreateClient();
            var result = client.GetProposals(credentials.Username, credentials.Password);
            var query = from proposal in result
                        select new HashProposal
                        {
                            User = proposal.User,
                            Hash = proposal.Hash,
                            Link = proposal.Link,
                            Added = proposal.Added,
                        };

            return query.ToArray();
        }

        public void AcceptProposal(HashCredentials credentials, HashProposal proposal)
        {
            var client = HashGateway.CreateClient();
            var info = new ROrganizerProxy.ProposalInfo { User = proposal.User, Hash = proposal.Hash, Link = proposal.Link, Added = proposal.Added };
            var result = client.AcceptProposal(credentials.Username, credentials.Password, info);
        }
    }
}
